﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UlsStudio.Engine.Parsers;

namespace UlsStudio.Engine
{
    /// <summary>
    /// ULS log entry loaded from a file
    /// </summary>
    public class FileLoadedUlsLogEntry : AbstractUlsLogEntry
    {
        /// <summary>
        /// Load a log entry from a line
        /// </summary>
        public static AbstractUlsLogEntry LoadFromLine(string logFileLine, UlsLineParser lineParser)
        {
            FileLoadedUlsLogEntry f = new FileLoadedUlsLogEntry();

            // Split line
            int lineTokenCount = 0; string[] lineTokens = null;
            try
            {
                lineTokens = lineParser.GetUlsTokenFromLine(logFileLine, out lineTokenCount);
            }
            catch (Exception ex)
            {
                string msg = string.Format("Critical error '{0}' parsing line: ###'{1}'###", ex.Message, logFileLine);
                Logging.Writeline(msg);
                f.Level = "Critical";
                f.Message = msg;
                return f;
            }
            


            // Sanity
            if (lineTokenCount < Constants.ULS_ENTRY_EXPECTED_TOKEN_COUNT) { return new EmptyUlsLogEntry(); }

            // Parse & clean each token
            DateTime timeStamp = DateTime.MinValue;
            string timeStampStr = CleanString(lineTokens[Constants.ULS_COL_IDX_TIME]);

            DateTime dateTime =
                    DateTime.ParseExact(timeStampStr, Constants.ULS_DATE_FORMAT,
                    System.Globalization.CultureInfo.InvariantCulture);

            f.DateTime = dateTime;
            f.DateTimeString = timeStampStr;
            f.Process = CleanString(lineTokens[Constants.ULS_COL_IDX_PROCESS]);
            f.ThreadID = CleanString(lineTokens[Constants.ULS_COL_IDX_TID]);
            f.Area = CleanString(lineTokens[Constants.ULS_COL_IDX_AREA]);
            f.Category = CleanString(lineTokens[Constants.ULS_COL_IDX_CATEGORY]);
            f.EventID = CleanString(lineTokens[Constants.ULS_COL_IDX_EVENTID]);
            f.Level = CleanString(lineTokens[Constants.ULS_COL_IDX_LEVEL]);
            
            f.Message = CleanString(lineTokens[Constants.ULS_COL_IDX_MESSAGE]);
            
            // Format for stack-trace messages
            f.Message = UlsLineParser.FormatStackTraceMessages(f.Message);

            // Grab GUID if there is one
            if (lineTokenCount > 8)
            {
                string guidString = CleanString(lineTokens[Constants.ULS_COL_IDX_CORRELATION]);
                Guid g = Guid.Empty; bool validGuid = false;
                try
                {
                    g = new Guid(guidString);
                    validGuid = true;
                }
                catch (Exception)
                {

                }
                if (validGuid)
                {
                    f.Correlation = g;
                }
            }

            return f;
        }

        /// <summary>
        /// Trims whitespace from string - accepts nulls too
        /// </summary>
        public static string CleanString(string inString)
        {
            if (string.IsNullOrEmpty(inString)) { return string.Empty; }
            else { return inString.Trim(); }
        }
    }
}
